#include <FileSystem/FAT32.h>
#include <FileSystem/FileAPI.h>
#include <IntExcept/Error.h>
#include <Memory/Heap.h>
#include <Kernel/GlobalData.h>
#include <FileSystem/Disk.h>
#include <Utility/CLib.h>

BOOL SimpleReadFile(
    LPFileObject lpFileObj,
    LPVOID lpBuffer,
    DWORD nNumberOfBytesToRead,
    LPDWORD lpNumberOfBytesRead
)
{
    if (lpFileObj->dwCurrentCluster == FAT32_RESERVED)
    {
        goto on_corrupt;
    }
    if (lpFileObj->dwCurrentCluster == FAT32_EOC)
    {
        goto on_eof;
    }
    DWORD nNumberOfBytesRead = 0;
    QWORD qwBegin = (QWORD)lpFileObj->dwFilePointer;
    QWORD qwEnd = (QWORD)lpFileObj->dwFilePointer + nNumberOfBytesToRead;
    BOOL bRet = TRUE;
    LPBYTE buf = NULL;
    if (qwBegin % 4096 != 0 || qwEnd % 4096 != 0)
    {
        buf = HeapAllocate(g_lpKernelHeap, 0, 4096);
    }
    /* 起始位置不在簇的边界上 */
    if (bRet && qwBegin % 4096 != 0)
    {
        ReadDisk(buf, GetFirstSectorOfFAT32Cluster(&g_BPB, lpFileObj->dwCurrentCluster), 8);
        while (lpFileObj->dwFilePointer % 4096 != 0)
        {
            if (lpFileObj->dwFilePointer >= lpFileObj->lpFCB->dwFileSize)
            {
                goto on_eof;
            }
            *((LPBYTE)lpBuffer + nNumberOfBytesRead) = buf[lpFileObj->dwFilePointer % 4096];
            nNumberOfBytesRead++;
            lpFileObj->dwFilePointer++;
        }
        lpFileObj->dwCurrentCluster = GetFAT32Entry(&g_BPB, (DWORD)lpFileObj->dwCurrentCluster);
    }
    /* 读取连续的簇 */
    for (LONGLONG i = lpFileObj->dwFilePointer / 4096; i < qwEnd / 4096; i++)
    {
        if (lpFileObj->dwCurrentCluster == FAT32_RESERVED)
        {
            goto on_corrupt;
        }
        if (lpFileObj->dwCurrentCluster == FAT32_EOC)
        {
            goto on_eof;
        }
        if (lpFileObj->dwFilePointer >= lpFileObj->lpFCB->dwFileSize)
        {
            goto on_eof;
        }
        ReadDisk((LPBYTE)lpBuffer + nNumberOfBytesRead, GetFirstSectorOfFAT32Cluster(&g_BPB, lpFileObj->dwCurrentCluster), 8);
        nNumberOfBytesRead += 4096; /* 一次读取一个簇 */
        lpFileObj->dwFilePointer += 4096;
        lpFileObj->dwCurrentCluster = GetFAT32Entry(&g_BPB, lpFileObj->dwCurrentCluster);
    }
    /* 结束位置不在簇的边界上 */
    if (qwEnd % 4096 != 0 && IsClusterValid(lpFileObj->dwCurrentCluster))
    {
        if (lpFileObj->dwCurrentCluster == FAT32_RESERVED)
        {
            goto on_corrupt;
        }
        if (lpFileObj->dwCurrentCluster == FAT32_EOC)
        {
            goto on_eof;
        }
        ReadDisk(buf, GetFirstSectorOfFAT32Cluster(&g_BPB, lpFileObj->dwCurrentCluster), 8);
        while (lpFileObj->dwFilePointer % 4096 != 0)
        {
            if (lpFileObj->dwFilePointer >= lpFileObj->lpFCB->dwFileSize)
            {
                goto on_eof;
            }
            *((LPBYTE)lpBuffer + nNumberOfBytesRead) = buf[lpFileObj->dwFilePointer % 4096];
            nNumberOfBytesRead++;
            lpFileObj->dwFilePointer++;
        }
    }
ret:
    if (lpNumberOfBytesRead)
    {
        *lpNumberOfBytesRead = nNumberOfBytesRead;
    }
    return bRet;
on_eof:
    SetLastError(ERROR_HANDLE_EOF);
    lpFileObj->dwFilePointer = EOF;
    bRet = FALSE;
    goto ret;
on_corrupt:
    SetLastError(ERROR_FILE_CORRUPT);
    bRet = FALSE;
    goto ret;
}